# -*- coding: utf-8 -*-

import time
import base64
import logging
import traceback

from odoo import fields, api
from odoo.tools.safe_eval import safe_eval
from odoo.http import request
from odoo.exceptions import ValidationError
from odoo_contrib import models as contrib_models

from ..utils.settings import Settings
from ..utils.exceptions import FrontendException

logger = logging.getLogger(__name__)
_sentinel = object()


class Exhibit(contrib_models.SchemaModel):
    _name = 'exhibition.exhibit'
    _description = 'Exhibit for exhibition APP'
    _order = 'sorting_weight desc,create_date desc'

    name = fields.Char(string='名称', required=True)
    desc = fields.Html(string='描述', required=True)
    view_count = fields.Integer(string='浏览次数', default=0)
    spec = fields.Char(string='展品规格')
    code = fields.Char(string='展品编号')

    qrcode = fields.Many2one('ir.attachment', string='展品二维码')

    enabled = fields.Boolean(string='是否展示', default=True)

    images = fields.Many2many('ir.attachment', string='展品图片')

    video = fields.Binary(
        string='展品视频',
        attachment=True,
    )
    video_filename = fields.Char(string='视频文件名')

    # categories = fields.Many2many('exhibition.category', domain='[("enabled", "=", True)]',)
    categories = fields.Many2many('exhibition.category',)

    pinned = fields.Boolean(string='是否置顶', default=False)
    weight = fields.Integer(string='排序权重', default=100)
    # not working
    # sorting_weight = fields.Integer(compute='_compute_sorting_weight', store=True)
    sorting_weight = fields.Integer(readonly=True)

    label_card_html = fields.Html(string='展品标签', compute='_compute_label_card_html')

    @api.constrains('weight')
    def _check_weight_range(self):
        for exhibit in self:
            if exhibit.weight < 0 or exhibit.weight > 9999:
                raise ValidationError('展品排序权重范围: 0 - 9999')

    @api.multi
    def been_viewed(self):
        for exhibit in self:
            exhibit.sudo().write({'view_count': exhibit.view_count + 1})

    @api.multi
    def been_visited(self):
        try:
            for exhibit in self:
                self.env['exhibition.exhibit_visit_history'].create([{
                    'wechat_uid': request.wechat_user.id,
                    'exhibit_id': exhibit.id,
                }])
        except:
            logger.error(
                'Error while record exhibit visit history. Err: %s',
                traceback.format_exc(),
            )
            raise FrontendException(
                errcode=200650,
            )

    @api.multi
    def generate_qrcode(self):
        for exhibit in self:
            scene_data = {
                'exhibitId': exhibit.id,
            }
            page = Settings().exhibit_page_path
            miniapp = self.env['wechat.miniapp'].sudo().search([
                ('default', '=', True),
            ], limit=1)
            if not miniapp:
                logger.error('No default miniapp found. EXIT')
            mini_app_adaptor = miniapp.get_adaptor()

            binary = mini_app_adaptor.get_wechat_qrcode(scene_data, page)
            # with open('/Users/simonq/dev/odoo/exhibition/models/qrcode.jpeg', 'rb') as f:
            #     binary = f.read()
            b64_encoded = base64.b64encode(binary)
            attachment = self.env['ir.attachment'].sudo().create([{
                'name': 'qrcode_exhibit_{}'.format(exhibit.id),
                'res_model': 'exhibition.exhibit',
                'res_field': 'qrcode',
                'res_id': exhibit.id,
                'type': 'binary',
                'datas': b64_encoded,
            }])
            exhibit.sudo().write({'qrcode': attachment.id})

    # @api.depends('name')
    def _compute_label_card_html(self):
        report = self.env['ir.actions.report']._get_report_from_name('exhibition.label_card_content')
        context = dict(self.env.context)

        for exhibit in self:
            html = report.with_context(context).render_qweb_html([exhibit.id], {})
            exhibit.label_card_html = html[0].decode('utf8')

    def _get_label_card_attachment(self):
        report = self.env['ir.actions.report'].sudo().search([
            ('model', '=', self._name),
        ], limit=1)
        if not report:
            return False
        doc_name = safe_eval(report.attachment, {'object': self, 'time': time})
        doc = self.env['ir.attachment'].sudo().search([
            ('datas_fname', '=', doc_name),
            ('res_model', '=', report.model),
            ('res_id', '=', self.id)
        ], limit=1)
        return doc

    # @api.constrains('name', 'code', 'spec', 'qrcode')
    def _expire_label_card(self):
        reports = self.env['ir.actions.report'].sudo().search([
            ('model', '=', self._name),
        ])
        for report in reports:
            doc_name = safe_eval(report.attachment, {'object': self, 'time': time})
            doc = self.env['ir.attachment'].sudo().search([
                ('datas_fname', '=', doc_name),
                ('res_model', '=', report.model),
                ('res_id', '=', self.id)
            ], limit=1)
            if doc:
                doc.sudo().unlink()
                logger.info('Deleted related label card due to exhibit info changed. exhibit_id: %s', self.id)

    @api.model
    def expire_all_label_card(self):
        exhibits = self.search([])
        for exhibit in exhibits:
            exhibit._expire_label_card()

    # not working
    # @api.multi
    # @api.depends('weight', 'pinned')
    # def _compute_sorting_weight(self):
    #     for exhibit in self:
    #         print(exhibit.weight, exhibit.pinned)
    #         exhibit.sorting_weight = exhibit.weight * (10 if exhibit.pinned else 1)

    @api.model_create_multi
    def create(self, vals_list):
        exhibits = super().create(vals_list)
        for exhibit in exhibits:
            exhibit.generate_qrcode()
            exhibit.sorting_weight = exhibit.weight * (10 if exhibit.pinned else 1)
        return exhibits

    @api.multi
    def write(self, vals):
        card_label_field_dependencies = ('name', 'code', 'spec', 'qrcode')
        for exhibit in self:
            for k, v in vals.items():
                if k not in card_label_field_dependencies:
                    continue
                if v != getattr(exhibit, k, _sentinel):
                    exhibit._expire_label_card()
                    break

        if 'weight' in vals or 'pinned' in vals:
            weight = vals.get('weight') or self[0].weight
            pinned = vals['pinned'] if 'pinned' in vals else self[0].pinned
            vals['sorting_weight'] = weight + (10000 if pinned else 0)
        return super().write(vals)

    @api.multi
    def unlink(self):
        for exhibit in self:
            exhibit.enabled = False
        return True

    @api.multi
    def toggle_enabled(self):
        for exhibit in self:
            exhibit.enabled = not exhibit.enabled

    @api.multi
    def toggle_pinned(self):
        for exhibit in self:
            exhibit.pinned = not exhibit.pinned

    def qrcode_popup(self):
        if not self.qrcode:
            try:
                self.generate_qrcode()
            except:
                logger.error(
                    'error while generating qrcode: %s',
                    traceback.format_exc(),
                )
        return {
            'type': 'ir.actions.act_window',
            'name': '查看展品标签',
            'res_model': 'exhibition.exhibit',
            'view_id': self.env.ref('exhibition.label_card_popup_view').id,
            'res_id': self.id,
            # 'view_type': 'tree',
            'view_mode': 'tree',
            # 'context': {'active_ids': active_ids, 'active_model': active_model},
            'context': {'search_default_id': self.ids[0]},
            'target': 'new',
        }
